﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Utilities;
using System.Text.RegularExpressions;
using Microsoft.SharePoint;

namespace Sapiens.at.SharePoint.Utils
{
    /// <summary>
    /// Methods that support conversion tasks.
    /// </summary>
    public static class Conversion
    {
        /// <summary>
        /// Safely casts a value into a defined type. If the cast can't be done, the default value of the result type is returned.
        /// </summary>
        /// <remarks>
        /// <para>The method first checks, if the value is directly convertable. If not, all special rules (see below) are processed if there is a rule
        /// for the given type. If there is still no proper cast, the value is converted using the <see cref="Convert.ChangeType(object,Type)"/> method.</para><para>
        /// If this method fails you probably have to extend it with a special rule for a datatype. The following types are currently handled
        /// special:
        /// <list type="bullet">
        ///     <item><see cref="DateTime"/></item>
        /// </list></para>
        /// </remarks>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T SafeCast<T>(object value)
        {
            if (value is T) { return (T)value; }
            //if (value != null && value.GetType().IsAssignableFrom(typeof(T))) { return (T)value; }
            try
            {
                if (typeof(T) == typeof(DateTime) && value is string)
                { // special rule for DateTime casting
                    if (Regex.IsMatch((string)value, @"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$"))
                    {
                        return (T)(object)SPUtility.CreateDateTimeFromISO8601DateTimeString(value.ToString());
                    }
                    else if (((string)value).StartsWith("0x"))
                    {
                        //In some cases DateTime field values come to the event in weird hex format
                        //This seems to occur only with Office 2007 documents
                        //The hexadecimal value represents the number of ticks since 1/1/1600
                        return (T)(object)new DateTime(long.Parse(value.ToString().Replace("0x", "").Replace("|", ""), System.Globalization.NumberStyles.HexNumber)).AddYears(1600).ToLocalTime();
                    }
                }
                if (typeof(T) == typeof(bool))
                {
                    bool bValue = false;
                    if (!bool.TryParse(Convert.ToString(value), out bValue))
                    {
                        int iValue = 0;
                        if (int.TryParse(Convert.ToString(value), out iValue))
                            bValue = (iValue == 1) ? true : false;
                    }
                    return (T)(object)bValue;
                }
                if (typeof(T) == typeof(double) || typeof(T) == typeof(decimal) || typeof(T) == typeof(float))
                {
                    return (T)Convert.ChangeType(value, typeof(T), new System.Globalization.NumberFormatInfo());
                }
                if (typeof(T) == typeof(SPFieldLookupValue))
                {
                    return (T)(object)new SPFieldLookupValue(Convert.ToString(value));
                }
                if (!(value is IConvertible)) { value = value == null ? null : value.ToString(); }
                return (T)Convert.ChangeType(value, typeof(T));
            }
            catch // Review: Dangerous to catch all exceptions
            { // Conversion went wrong, return default value for the type
                return default(T);
            }
        }
    }
}
